package com.yeziji.common;

import com.google.common.base.Joiner;
import com.mybatisflex.core.paginate.Page;
import com.yeziji.constant.SystemCode;
import com.yeziji.utils.expansion.Lists2;
import com.yeziji.utils.expansion.MessageFormat2;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

/**
 * 通用返回
 *
 * @author hwy
 * @since 2023/10/17 0:46
 **/
@Data
@SuperBuilder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class CommonResult<T> {
    /**
     * 状态码
     */
    private Integer code;

    /**
     * 返回信息体
     */
    private String msg;

    /**
     * 返回数据体
     */
    private T data;

    /**
     * 是否成功
     */
    private boolean success;

    /**
     * 失败返回结果
     *
     * @param errorEnum 错误枚举
     * @return {@link CommonResult} 响应结果
     */
    public static <T> CommonResult<T> failed(CommonErrorEnum errorEnum) {
        return new CommonResult<>(errorEnum.getCode(), errorEnum.getShowLangMsg(), null, false);
    }

    public static <T> CommonResult<T> success(T data) {
        return new CommonResult<>(SystemCode.SUCCESS.getCode(), SystemCode.SUCCESS.getLangDesc(), data, true);
    }

    public static <T> CommonResult<T> success(T data, String message) {
        return new CommonResult<>(SystemCode.SUCCESS.getCode(), MessageFormat2.language(message), data, true);
    }

    public static <T, O> CommonResult<O> success(T data, Function<T, O> convert) {
        return new CommonResult<>(SystemCode.SUCCESS.getCode(), SystemCode.SUCCESS.getLangDesc(), convert.apply(data), true);
    }

    public static <T, O> CommonResult<List<O>> success(List<T> dataList, Function<T, O> convert) {
        return new CommonResult<>(SystemCode.SUCCESS.getCode(), SystemCode.SUCCESS.getLangDesc(), Lists2.transforms(dataList, convert), true);
    }

    public static <T> CommonResult<T> success(String message) {
        return new CommonResult<>(SystemCode.SUCCESS.getCode(), MessageFormat2.language(message), null, true);
    }

    public static <T> CommonResult<CommonPage<T>> successPage(Page<T> data) {
        return new CommonResult<>(SystemCode.SUCCESS.getCode(), SystemCode.SUCCESS.getLangDesc(), CommonPage.build(data), true);
    }

    public static <T, O> CommonResult<CommonPage<T>> successPage(Page<O> data, Function<O, T> transformer) {
        return new CommonResult<>(SystemCode.SUCCESS.getCode(), SystemCode.SUCCESS.getLangDesc(), CommonPage.convert(data, transformer), true);
    }

    /**
     * 失败返回结果
     *
     * @param message 提示信息
     * @return {@link CommonResult} 响应结果
     */
    public static <T> CommonResult<T> failed(String message) {
        return new CommonResult<>(SystemCode.ERROR.getCode(), MessageFormat2.language(message), null, false);
    }

    /**
     * 失败返回结果
     *
     * @param code    状态码
     * @param message 提示信息
     * @return {@link CommonResult} 响应结果
     */
    public static <T> CommonResult<T> failed(int code, String message) {
        return new CommonResult<>(code, MessageFormat2.language(message), null, false);
    }

    /**
     * 未授权返回结果
     */
    public static <T> CommonResult<T> forbidden() {
        return CommonResult.failed(CommonErrorMsg.FORBIDDEN);
    }

    /**
     * 未授权返回结果
     */
    public static <T> CommonResult<T> unauthorized() {
        return CommonResult.failed(CommonErrorMsg.UNAUTHORIZED);
    }

    /**
     * 校验异常
     */
    public static <T> CommonResult<T> validate(BindingResult result) {
        List<FieldError> fieldErrors = result.getFieldErrors();
        List<String> messages = new ArrayList<>();
        for (FieldError fieldError : fieldErrors) {
            messages.add(fieldError.getDefaultMessage());
        }
        return new CommonResult<>(SystemCode.VALIDATE_FAILED.getCode(), Joiner.on(CommonSymbol.CAESURA_SIGN).join(messages), null, false);
    }
}